/*******************************************************************************
*  file    : networkdataprovider.cpp
*  created : 19.08.2014
*  author  : Slyshyk Oleksiy (alexSlyshyk@gmail.com)
*******************************************************************************/

#include "networkdataprovider.hpp"
#include <QTcpSocket>

#include <interfaces.hpp>
#include <dataobject/dataobject.hpp>
#include <QTimer>
#include <qlogger.hpp>
namespace
{
QLogger * l = QLoggerEngine::getLogger("Core");
}


NetworkDataProvider::NetworkDataProvider(QObject *parent) :
    DataProvider(parent)
{
    socket_ = new QTcpSocket(this);

    connect(socket_, &QTcpSocket::connected, [this](){logInfo(l) << "Connected to " << socket_->peerAddress().toString();} );
    connect(socket_, &QTcpSocket::readyRead, this, &NetworkDataProvider::onDataReady );
    connect(socket_, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSockError(QAbstractSocket::SocketError)) );
}

QString NetworkDataProvider::name() const
{
    return QStringLiteral("NetworkDataProvider");
}

bool NetworkDataProvider::connectToHost(const QHostAddress &address, quint16 port)
{
    addr_ = address;
    port_ = port;
    if(socket_)
        {
            socket_->connectToHost(address, port);
            return socket_->waitForConnected(3000);
        }

    return false;
}

void NetworkDataProvider::onDataReady()
{
    QByteArray st;
    st = socket_->readAll();

    for( auto ch : st)
        {
            buff_.append(ch);
            if(ch == '\n')
                {
                    strings_ << QString(buff_);
                    buff_.clear();
                }
        }

    for(const QString& s : strings_)
        {
            QJsonDocument document = QJsonDocument::fromJson(s.toLatin1());
            DataObjectPtr data_obj = DataObjectPtr(new DataObject);
            data_obj->updateFromJson(document);

            emit dataObjectReady(data_obj);
        }
    strings_.clear();
}

void NetworkDataProvider::onSockError(QAbstractSocket::SocketError socketError)
{
    logError(l) << "Socket error " << static_cast<int>(socketError)
                << "  " << socket_->errorString();

    socket_->abort();
    QTimer::singleShot(500,this, SLOT(reconnect()) );
}

void NetworkDataProvider::reconnect()
{
    socket_->connectToHost(addr_, port_);
}
